#include "Materials.h"

using namespace cagd;

Material::Material(
        const Color& front_ambient,
        const Color& front_diffuse,
        const Color& front_specular,
        const Color& front_emissive,
        GLfloat front_shininess,
        const Color& back_ambient,
        const Color& back_diffuse,
        const Color& back_specular,
        const Color& back_emissive,
        GLfloat back_shininess):
        _front_ambient(front_ambient),
        _front_diffuse(front_diffuse),
        _front_specular(front_specular),
        _front_emmisive(front_emissive),
        _front_shininess(front_shininess),
        _back_ambient(back_ambient),
        _back_diffuse(back_diffuse),
        _back_specular(back_specular),
        _back_emmisive(back_emissive),
        _back_shininess(back_shininess)
{}

GLvoid Material::SetAmbientColor(GLenum face, GLfloat r, GLfloat g, GLfloat b, GLfloat a)
{
    switch (face)
    {
    case GL_FRONT:
        _front_ambient.r = r;
        _front_ambient.g = g;
        _front_ambient.b = b;
        _front_ambient.a = a;
        break;
    case GL_BACK:
        _back_ambient.r = r;
        _back_ambient.g = g;
        _back_ambient.b = b;
        _back_ambient.a = a;
        break;
    case GL_FRONT_AND_BACK:
        _front_ambient.r = r;
        _front_ambient.g = g;
        _front_ambient.b = b;
        _front_ambient.a = a;
        _back_ambient.r = r;
        _back_ambient.g = g;
        _back_ambient.b = b;
        _back_ambient.a = a;
        break;
    }
}

GLvoid Material::SetAmbientColor(GLenum face, const Color &c)
{
    switch (face)
    {
    case GL_FRONT:
        _front_ambient = c;
        break;
    case GL_BACK:
        _back_ambient = c;
        break;
    case GL_FRONT_AND_BACK:
        _front_ambient = c;
        _back_ambient = c;
        break;
    }
}

GLvoid Material::SetDiffuseColor(GLenum face, GLfloat r, GLfloat g, GLfloat b, GLfloat a)
{
    switch (face)
    {
    case GL_FRONT:
        _front_diffuse.r = r;
        _front_diffuse.g = g;
        _front_diffuse.b = b;
        _front_diffuse.a = a;
        break;
    case GL_BACK:
        _back_diffuse.r = r;
        _back_diffuse.g = g;
        _back_diffuse.b = b;
        _back_diffuse.a = a;
        break;
    case GL_FRONT_AND_BACK:
        _front_diffuse.r = r;
        _front_diffuse.g = g;
        _front_diffuse.b = b;
        _front_diffuse.a = a;
        _back_diffuse.r = r;
        _back_diffuse.g = g;
        _back_diffuse.b = b;
        _back_diffuse.a = a;
        break;
    }
}

GLvoid Material::SetDiffuseColor(GLenum face, const Color &c)
{
    switch (face)
    {
    case GL_FRONT:
        _front_diffuse = c;
        break;
    case GL_BACK:
        _back_diffuse = c;
        break;
    case GL_FRONT_AND_BACK:
        _front_diffuse = c;
        _back_diffuse = c;
        break;
    }
}

GLvoid Material::SetEmissiveColor(GLenum face, GLfloat r, GLfloat g, GLfloat b, GLfloat a)
{
    switch (face)
    {
    case GL_FRONT:
        _front_emmisive.r = r;
        _front_emmisive.g = g;
        _front_emmisive.b = b;
        _front_emmisive.a = a;
        break;
    case GL_BACK:
        _back_emmisive.r = r;
        _back_emmisive.g = g;
        _back_emmisive.b = b;
        _back_emmisive.a = a;
        break;
    case GL_FRONT_AND_BACK:
        _front_emmisive.r = r;
        _front_emmisive.g = g;
        _front_emmisive.b = b;
        _front_emmisive.a = a;
        _back_emmisive.r = r;
        _back_emmisive.g = g;
        _back_emmisive.b = b;
        _back_emmisive.a = a;
        break;
    }
}

GLvoid Material::SetEmissiveColor(GLenum face, const Color &c)
{
    switch (face)
    {
    case GL_FRONT:
        _front_emmisive = c;
        break;
    case GL_BACK:
        _back_emmisive = c;
        break;
    case GL_FRONT_AND_BACK:
        _front_emmisive = c;
        _back_emmisive = c;
        break;
    }
}

GLvoid Material::SetSpecularColor(GLenum face, GLfloat r, GLfloat g, GLfloat b, GLfloat a)
{
    switch (face)
    {
    case GL_FRONT:
        _front_specular.r = r;
        _front_specular.g = g;
        _front_specular.b = b;
        _front_specular.a = a;
        break;
    case GL_BACK:
        _back_specular.r = r;
        _back_specular.g = g;
        _back_specular.b = b;
        _back_specular.a = a;
        break;
    case GL_FRONT_AND_BACK:
        _front_specular.r = r;
        _front_specular.g = g;
        _front_specular.b = b;
        _front_specular.a = a;
        _back_specular.r = r;
        _back_specular.g = g;
        _back_specular.b = b;
        _back_specular.a = a;
        break;
    }
}

GLvoid Material::SetSpecularColor(GLenum face, const Color &c)
{
    switch (face)
    {
    case GL_FRONT:
        _front_specular = c;
        break;
    case GL_BACK:
        _back_specular = c;
        break;
    case GL_FRONT_AND_BACK:
        _front_specular = c;
        _back_specular = c;
        break;
    }
}

GLvoid Material::SetShininess(GLenum mface, GLfloat shininess)
{
    switch (mface)
    {
    case GL_FRONT:
        _front_shininess = shininess;
        break;
    case GL_BACK:
        _back_shininess = shininess;
        break;
    case GL_FRONT_AND_BACK:
        _front_shininess = shininess;
        _back_shininess = shininess;
        break;
    }
}

GLvoid Material::SetTransparency(GLfloat alpha)
{
    _front_ambient.a = _front_diffuse.a = _front_emmisive.a = _front_specular.a = alpha;
    _back_ambient.a = _back_diffuse.a = _back_emmisive.a = _back_specular.a = alpha;
}

GLboolean Material::IsTransparent() const
{
    return (_front_ambient.a < 1.0f || _front_diffuse.a < 1.0f || _front_emmisive.a < 1.0f || _front_specular.a < 1.0f ||
        _back_ambient.a < 1.0f || _back_diffuse.a < 1.0f || _back_emmisive.a < 1.0f || _back_specular.a < 1.0f);
}

GLvoid Material::Apply()
{
    glMaterialfv(GL_FRONT, GL_AMBIENT,  &_front_ambient.r);
    glMaterialfv(GL_FRONT, GL_DIFFUSE,  &_front_diffuse.r);
    glMaterialfv(GL_FRONT, GL_SPECULAR, &_front_specular.r);
    glMaterialfv(GL_FRONT, GL_EMISSION,  &_front_emmisive.r);
    glMaterialf(GL_FRONT, GL_SHININESS,  _front_shininess);

    glMaterialfv(GL_BACK, GL_AMBIENT,  &_back_ambient.r);
    glMaterialfv(GL_BACK, GL_DIFFUSE,  &_back_diffuse.r);
    glMaterialfv(GL_BACK, GL_SPECULAR, &_back_specular.r);
    glMaterialfv(GL_BACK, GL_EMISSION,  &_back_emmisive.r);
    glMaterialf(GL_BACK, GL_SHININESS,  _back_shininess);
}

Material
// brass
cagd::MatFBBrass = Material(
        Color(0.329412, 0.223529, 0.027451, 0.4),
        Color(0.780392, 0.568627, 0.113725, 0.6),
        Color(0.992157, 0.941176, 0.807843, 0.8),
        Color(0.000000, 0.000000 ,0.000000, 0.0),
        27.8974,
        Color(0.329412, 0.223529, 0.027451, 0.4),
        Color(0.780392, 0.568627, 0.113725, 0.6),
        Color(0.992157, 0.941176, 0.807843, 0.8),
        Color(0.000000, 0.000000, 0.000000, 0.0),
        27.8974),
// gold
cagd::MatFBGold = Material(
        Color(0.247250, 0.199500, 0.074500, 0.4),
        Color(0.751640, 0.606480, 0.226480, 0.6),
        Color(0.628281, 0.555802, 0.366065, 0.8),
        Color(0.000000, 0.000000, 0.000000, 0.0),
        51.2,
        Color(0.247250, 0.199500, 0.074500, 0.4),
        Color(0.751640, 0.606480, 0.226480, 0.6),
        Color(0.628281, 0.555802, 0.366065, 0.8),
        Color(0.000000, 0.000000, 0.000000, 0.0),
        51.2),
// silver
cagd::MatFBSilver = Material(
        Color(0.192250, 0.192250, 0.192250, 0.4),
        Color(0.507540, 0.507540, 0.507540, 0.6),
        Color(0.508273, 0.508273, 0.508273, 0.8),
        Color(0.000000, 0.000000, 0.000000, 0.0),
        51.2,
        Color(0.192250, 0.192250, 0.192250, 0.4),
        Color(0.507540, 0.507540, 0.507540, 0.6),
        Color(0.508273, 0.508273, 0.508273, 0.8),
        Color(0.000000, 0.000000, 0.000000, 0.0),
        51.2),
// emerald
        cagd::MatFBEmerald = Material(
        Color(0.021500, 0.174500, 0.021500, 0.4),
        Color(0.075680, 0.614240, 0.075680, 0.6),
        Color(0.633000, 0.727811, 0.633000, 0.8),
        Color(0.000000, 0.000000, 0.000000, 0.0),
        76.8,
        Color(0.021500, 0.174500, 0.021500, 0.4),
        Color(0.075680, 0.614240, 0.075680, 0.6),
        Color(0.633000, 0.727811, 0.633000, 0.8),
        Color(0.000000, 0.000000, 0.000000, 0.0),
        76.8),
// pearl
cagd::MatFBPearl = Material(
        Color(0.250000, 0.207250, 0.207250, 0.4),
        Color(1.000000, 0.829000, 0.829000, 0.6),
        Color(0.296648, 0.296648, 0.296648, 0.8),
        Color(0.000000, 0.000000, 0.000000, 0.0),
        11.264,
        Color(0.250000, 0.207250, 0.207250, 0.4),
        Color(1.000000, 0.829000, 0.829000, 0.6),
        Color(0.296648, 0.296648, 0.296648, 0.8),
        Color(0.000000, 0.000000, 0.000000, 0.0),
        11.264),
// ruby
cagd::MatFBRuby = Material(
        Color(0.174500, 0.011750, 0.011750, 0.4),
        Color(0.614240, 0.041360, 0.041360, 0.6),
        Color(0.727811, 0.626959, 0.626959, 0.8),
        Color(0.000000, 0.000000, 0.000000, 0.0),
        76.8,
        Color(0.174500, 0.011750, 0.011750, 0.4),
        Color(0.614240, 0.041360, 0.041360, 0.6),
        Color(0.727811, 0.626959, 0.626959, 0.8),
        Color(0.000000, 0.000000, 0.000000, 0.0),
        76.8),
// turquoise
cagd::MatFBTurquoise = Material(
        Color(0.100000, 0.187250, 0.174500, 0.4),
        Color(0.396000, 0.741510, 0.691020, 0.6),
        Color(0.297254, 0.308290, 0.306678, 0.8),
        Color(0.000000, 0.000000, 0.000000, 0.0),
        12.8,
        Color(0.100000, 0.187250, 0.174500, 0.4),
        Color(0.396000, 0.741510, 0.691020, 0.6),
        Color(0.297254, 0.308290, 0.306678, 0.8),
        Color(0.000000, 0.000000, 0.000000, 0.0),
        12.8);
